package org.example.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Aspect
public class MyAdvice {
    @Pointcut("execution(void org.example.dao.BookDao.update())")
    private void pt() {
    }

    @Before("pt()")
    public void method() {
        System.out.println(System.currentTimeMillis());
    }

    @Pointcut("execution(void org.example.dao.BrandDao.update())")
    private void pt1() {
    }

    @Pointcut("execution(int org.example.dao.BrandDao.select())")
    private void pt2() {
    }

    @Pointcut("execution(* org.example.dao.*Dao.test(..))")
    private void pt3() {
    }

    @Before("pt1()")
    public void before() {
        System.out.println("MyAdvice-before..");
    }

    @After("pt1()")
    public void after() {
        System.out.println("MyAdvice-after..");
    }

    @Around("pt2()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("MyAdvice-around-before..");
        Object o = proceedingJoinPoint.proceed();
        System.out.println("MyAdvice-around-after..");
        return o;
    }

    @Around("pt3()")
    public Object testAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //获取执行签名信息，获取执行类型（接口名），获取执行操作名称（方法名）
        Signature signature = proceedingJoinPoint.getSignature();
        Class declaringType = signature.getDeclaringType();
        long start = System.currentTimeMillis();
        String name = signature.getName();
        for (int i = 0; i < 10000; i++) {
            proceedingJoinPoint.proceed();
        }
        long end = System.currentTimeMillis();
        System.out.println("万次执行：" + declaringType + ":" + name + "......" + (end - start) + "ms");
        return null;
    }

    @AfterReturning("pt2()")
    public void afterReturning() {
        System.out.println("MyAdvice-afterReturning..");
    }

    @AfterThrowing("pt2()")
    public void afterThrowing() {
        System.out.println("MyAdvice-afterThrowing..");
    }

    @Pointcut("execution(* org.example.dao.MonkeyDao.findName(..))")
    private void pt4() {
    }

    //@Before("pt4()")
    public void before4(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        System.out.println("MyAdvice-before4-args:" + Arrays.toString(args));
    }

    //@After("pt4()")
    public void after4(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        System.out.println("MyAdvice-after4-args:" + Arrays.toString(args));
    }

    @Around("pt4()")
    public Object around4(ProceedingJoinPoint proceedingJoinPoint) {
        //获取参数、返回值、异常
        Object[] args = proceedingJoinPoint.getArgs();
        System.out.println("MyAdvice-around4-args:" + Arrays.toString(args));
        //处理参数
        args[0] = 666;
        Object o = null;
        try {
            o = proceedingJoinPoint.proceed(args);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("MyAdvice-around4-return:" + o);
        return o;
    }

    //@AfterReturning(value = "pt4()", returning = "ret")
    public void afterReturning4(JoinPoint joinPoint, Object ret) {
        Object[] args = joinPoint.getArgs();
        System.out.println("MyAdvice-afterReturning4-args:" + Arrays.toString(args));
        System.out.println("MyAdvice-afterReturning4-return:" + ret);
    }

    //@AfterThrowing(value = "pt4()", throwing = "throwable")
    public void afterThrowing4(Throwable throwable) {
        System.out.println("MyAdvice-afterThrowing4-throwable:" + throwable);
    }

}
